package com.cardone.platform.common.dao;

import java.util.List;
import java.util.Map;

import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;

import org.apache.commons.lang3.ArrayUtils;
import org.joda.time.DateTime;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;

import com.cardone.common.dto.PaginationDto;
import com.cardone.persistent.CommonDtoAttributes;
import com.cardone.persistent.builder.ModelArgs;
import com.cardone.persistent.builder.ModelBuilder;
import com.cardone.persistent.builder.ModelBuilderUtils;
import com.cardone.persistent.support.JdbcTemplateSupport;
import com.cardone.persistent.support.PaginationArgs;
import com.cardone.platform.common.dto.EntityRelationshipDto;

/**
 * 实体关系
 * 
 * @author yaoht
 * 
 */
@Getter
@Setter
public class EntityRelationshipJdbcDao implements EntityRelationshipDao {
	/**
	 * jdbcDao模板支持
	 */
	private JdbcTemplateSupport jdbcTemplateSupport;

	@Override
	@CacheEvict(value = EntityRelationshipDao.BEAN_ID, allEntries = true)
	public int deleteByCode(@NonNull EntityRelationshipDto deleteEntityRelationship, String... whereAndEqProperties) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(deleteEntityRelationship,
		        whereAndEqProperties));

		if (!(ArrayUtils.contains(whereAndEqProperties, CommonDtoAttributes.beginDate.name()) || ArrayUtils.contains(
		        whereAndEqProperties, CommonDtoAttributes.endDate.name()))) {
			modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());
		}

		return this.jdbcTemplateSupport.update(SqlIds.deleteByCode.id(), modelBuilder.build());
	}

	@Override
	@CacheEvict(value = EntityRelationshipDao.BEAN_ID, allEntries = true)
	public int deleteByCodeOrId(@NonNull EntityRelationshipDto deleteEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(deleteEntityRelationship));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.update(SqlIds.deleteByCode.id(), modelBuilder.build());
	}

	@Override
	@CacheEvict(value = EntityRelationshipDao.BEAN_ID, allEntries = true)
	public int deleteByIds(@NonNull EntityRelationshipDto deleteEntityRelationship) {
		ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder();

		modelBuilder.put(new String[] { DtoAttributes.ids.name() }, deleteEntityRelationship.getIds());

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.update(SqlIds.deleteByIds.id(), modelBuilder.build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_4)
	public <P> P findByCode(@NonNull Class<P> mappedClass, @NonNull EntityRelationshipDto findEntityRelationship,
	        String[] selectProperties, String... whereAndEqProperties) {
		final ModelBuilder modelBuilder = ModelBuilderUtils
		        .newModelBuilder(new ModelArgs(findEntityRelationship, whereAndEqProperties));

		modelBuilder.putTrueExtend(ModelBuilder.Constants.select.stringValue(), selectProperties);

		if (!(ArrayUtils.contains(whereAndEqProperties, CommonDtoAttributes.beginDate.name()) || ArrayUtils.contains(
		        whereAndEqProperties, CommonDtoAttributes.endDate.name()))) {
			modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());
		}

		return this.jdbcTemplateSupport.find(mappedClass, SqlIds.findByCode.id(), modelBuilder.build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_2)
	public <P> P findByCodeOrId(@NonNull Class<P> mappedClass, @NonNull EntityRelationshipDto findEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(findEntityRelationship));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.find(mappedClass, SqlIds.findByCode.id(), modelBuilder.build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_2)
	public <P> P findByName(@NonNull Class<P> mappedClass, @NonNull EntityRelationshipDto findEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(findEntityRelationship));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.find(mappedClass, SqlIds.findByName.id(), modelBuilder.build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_4)
	public <P> List<P> findListByCode(@NonNull Class<P> mappedClass, @NonNull EntityRelationshipDto findListEntityRelationship,
	        String[] selectProperties, String... whereAndEqProperties) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(findListEntityRelationship,
		        whereAndEqProperties));

		modelBuilder.putTrueExtend(ModelBuilder.Constants.select.stringValue(), selectProperties);

		if (!(ArrayUtils.contains(whereAndEqProperties, CommonDtoAttributes.beginDate.name()) || ArrayUtils.contains(
		        whereAndEqProperties, CommonDtoAttributes.endDate.name()))) {
			modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());
		}

		return this.jdbcTemplateSupport.findList(mappedClass, SqlIds.findByCode.id(), modelBuilder.build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_2)
	public <P> List<P> findListByCodeOrId(@NonNull Class<P> mappedClass, @NonNull EntityRelationshipDto findListEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(findListEntityRelationship));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.findList(mappedClass, SqlIds.findByCode.id(), modelBuilder.build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_2)
	public <P> List<P> findListByName(@NonNull Class<P> mappedClass, @NonNull EntityRelationshipDto findListEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(findListEntityRelationship));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.findList(mappedClass, SqlIds.findByName.id(), modelBuilder.build());
	}

	@Override
	@CacheEvict(value = EntityRelationshipDao.BEAN_ID, allEntries = true)
	public int insertByCode(@NonNull EntityRelationshipDto insertEntityRelationship, String... insertProperties) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(ModelBuilder.Constants.insert.stringValue(),
		        insertEntityRelationship, insertProperties));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.update(SqlIds.insertByCode.id(), modelBuilder.build());
	}

	@Override
	@CacheEvict(value = EntityRelationshipDao.BEAN_ID, allEntries = true)
	public int insertByCodeOrId(@NonNull EntityRelationshipDto insertEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(ModelBuilder.Constants.insert.stringValue(),
		        insertEntityRelationship));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.update(SqlIds.insertByCode.id(), modelBuilder.build());
	}

	@Override
	@CacheEvict(value = EntityRelationshipDao.BEAN_ID, allEntries = true)
	public int insertByName(@NonNull EntityRelationshipDto insertEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(ModelBuilder.Constants.insert.stringValue(),
		        insertEntityRelationship));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.update(SqlIds.insertByName.id(), modelBuilder.build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_2)
	public <P> PaginationDto<P> paginationByCode(@NonNull Class<P> mappedClass,
	        @NonNull EntityRelationshipDto paginationEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(paginationEntityRelationship));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport
		        .pagination(mappedClass, new PaginationArgs(SqlIds.readByCode.id(), SqlIds.findByCode.id(),
		                paginationEntityRelationship.getPaginationNo(), paginationEntityRelationship.getPaginationSize()), modelBuilder
		                .build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_1)
	public PaginationDto<Map<String, Object>> paginationByName(@NonNull EntityRelationshipDto paginationEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(paginationEntityRelationship));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport
		        .pagination(
		                new PaginationArgs(SqlIds.readByCode.id(), SqlIds.findByCode.id(), paginationEntityRelationship
		                        .getPaginationNo(), paginationEntityRelationship.getPaginationSize()), modelBuilder.build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_4)
	public <R> R readByCode(@NonNull Class<R> requiredType, String objectId, @NonNull EntityRelationshipDto readEntityRelationship,
	        String... whereAndEqProperties) {
		final ModelBuilder modelBuilder = ModelBuilderUtils
		        .newModelBuilder(new ModelArgs(readEntityRelationship, whereAndEqProperties));

		if (!(ArrayUtils.contains(whereAndEqProperties, CommonDtoAttributes.beginDate.name()) || ArrayUtils.contains(
		        whereAndEqProperties, CommonDtoAttributes.endDate.name()))) {
			modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());
		}

		return this.jdbcTemplateSupport.read(requiredType, SqlIds.readByCode.id(), objectId, modelBuilder.build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_2)
	public <R> R readByCodeNqId(@NonNull Class<R> requiredType, @NonNull EntityRelationshipDto readEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder();

		// final ModelBuilder modelBuilder =
		// ModelBuilderUtils.newModelBuilder().putExtend(null,
		// CommonDtoAttributes.code.name(), null,
		// readEntityRelationship.getCode());

		// if (StringUtils.isNotBlank(readEntityRelationship.getId())) {
		// modelBuilder.putExtend(ModelBuilder.WHERE_AND_NQ,
		// CommonDtoAttributes.id.name(), null, readEntityRelationship.getId());
		// }

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.read(requiredType, SqlIds.readByCode.id(), null, modelBuilder.build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_3)
	public <R> R readByCodeOrId(@NonNull Class<R> requiredType, String objectId, @NonNull EntityRelationshipDto readEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(readEntityRelationship));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.read(requiredType, SqlIds.readByCode.id(), objectId, modelBuilder.build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_3)
	public <R> R readByName(@NonNull Class<R> requiredType, String objectId, @NonNull EntityRelationshipDto readEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(readEntityRelationship));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.read(requiredType, SqlIds.readByName.id(), objectId, modelBuilder.build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_4)
	public <R> List<R> readListByCode(@NonNull Class<R> requiredType, String objectId,
	        @NonNull EntityRelationshipDto readListEntityRelationship, String... whereAndEqProperties) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(readListEntityRelationship,
		        whereAndEqProperties));

		if (!(ArrayUtils.contains(whereAndEqProperties, CommonDtoAttributes.beginDate.name()) || ArrayUtils.contains(
		        whereAndEqProperties, CommonDtoAttributes.endDate.name()))) {
			modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());
		}

		return this.jdbcTemplateSupport.readList(requiredType, SqlIds.readByCode.id(), objectId, modelBuilder.build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_3)
	public <R> List<R> readListByCodeOrId(@NonNull Class<R> requiredType, String objectId,
	        @NonNull EntityRelationshipDto readListEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(readListEntityRelationship));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.readList(requiredType, SqlIds.readByCode.id(), objectId, modelBuilder.build());
	}

	@Override
	@Cacheable(value = EntityRelationshipDao.BEAN_ID, key = com.cardone.common.cache.Constants.KEY_3)
	public <R> List<R> readListByName(@NonNull Class<R> requiredType, String objectId,
	        @NonNull EntityRelationshipDto readListEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(readListEntityRelationship));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.readList(requiredType, SqlIds.readByName.id(), objectId, modelBuilder.build());
	}

	@Override
	@CacheEvict(value = EntityRelationshipDao.BEAN_ID, allEntries = true)
	public void reload() {
	}

	@Override
	@CacheEvict(value = EntityRelationshipDao.BEAN_ID, allEntries = true)
	public int updateByCode(@NonNull EntityRelationshipDto updateEntityRelationship, String[] updateProperties,
	        String... whereAndEqProperties) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(ModelBuilder.Constants.update.stringValue(),
		        updateEntityRelationship, updateProperties), new ModelArgs(updateEntityRelationship, whereAndEqProperties));

		if (!(ArrayUtils.contains(whereAndEqProperties, CommonDtoAttributes.beginDate.name()) || ArrayUtils.contains(
		        whereAndEqProperties, CommonDtoAttributes.endDate.name()))) {
			modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());
		}

		return this.jdbcTemplateSupport.update(SqlIds.updateByCode.id(), modelBuilder.build());
	}

	@Override
	@CacheEvict(value = EntityRelationshipDao.BEAN_ID, allEntries = true)
	public int updateByCodeOrId(@NonNull EntityRelationshipDto updateEntityRelationship) {
		final ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder(new ModelArgs(updateEntityRelationship));

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.update(SqlIds.updateByCode.id(), modelBuilder.build());
	}

	@Override
	@CacheEvict(value = EntityRelationshipDao.BEAN_ID, allEntries = true)
	public int updateByIds(@NonNull EntityRelationshipDto updateEntityRelationship) {
		ModelBuilder modelBuilder = ModelBuilderUtils.newModelBuilder();

		modelBuilder.put(new String[] { CommonDtoAttributes.endDate.name() }, new DateTime().plusSeconds(-1));

		modelBuilder.put(new String[] { DtoAttributes.ids.name() }, updateEntityRelationship.getIds());

		modelBuilder.putTrue(ModelBuilder.Constants.whereAndBetween.stringValue(), CommonDtoAttributes.sysdate.name());

		return this.jdbcTemplateSupport.update(SqlIds.updateByIds.id(), modelBuilder.build());
	}
}